home *** CD-ROM | disk | FTP | other *** search
/ Aminet 1 (Walnut Creek) / Aminet - June 1993 [Walnut Creek].iso / usenet / sources / volume90 / util / snap_1_4 / part01 / source / saveilbm.c < prev    next >
C/C++ Source or Header  |  1990-02-11  |  6KB  |  221 lines

  1. /* Auto: make
  2. */
  3.  
  4. IMPORT BPTR SnapFile;
  5. IMPORT BYTE TranspBuf[];
  6.  
  7. #define ID(a,b,c,d) ((a << 24L) | (b << 16L) | (c << 8L) | (d))
  8.  
  9. struct ckHdr {
  10.     LONG ChunkName;
  11.     LONG ChunkSize;
  12. };
  13.  
  14. struct BitMapHeader
  15. {
  16.    UWORD w,h;
  17.    WORD  x,y;
  18.    UBYTE nPlanes;
  19.    UBYTE masking;
  20.    UBYTE compression;
  21.    UBYTE pad1;
  22.    UWORD transparentColor;
  23.    UBYTE xAspect, yAspect;
  24.    WORD  pageWidth, pageHeight;
  25. };
  26.  
  27. struct ckHdr FORM = {
  28.     ID('F','O','R','M'),
  29.     0L
  30. };
  31. LONG TYPE = ID('I','L','B','M');
  32.  
  33. struct ckHdr BMHD = {
  34.     ID('B','M','H','D'),
  35.     sizeof(struct BitMapHeader)
  36. };
  37. struct BitMapHeader BMHdr = {
  38.    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
  39. };
  40.  
  41. struct ckHdr CAMG = {
  42.     ID('C','A','M','G'),
  43.     4L
  44. };
  45. ULONG ViewMode = NULL;
  46.  
  47. struct ckHdr CMAP = {
  48.     ID('C','M','A','P'),
  49.     0L
  50. };
  51.  
  52. struct ckHdr BODY = {
  53.     ID('B','O','D','Y'),
  54.     0L
  55. };
  56.  
  57. UBYTE *buf;
  58. WORD bufcnt;
  59. ULONG totalsize;
  60.  
  61. WORD bumpmode;
  62. #define BUMP_CALC   1
  63. #define BUMP_SAVE   2
  64.  
  65. WORD bump(cnt, dataptr, size)
  66. WORD cnt;
  67. UBYTE *dataptr;
  68. WORD size;
  69. {
  70.     REGISTER LONG tsize = size;
  71.     if (tsize) {
  72.         totalsize += tsize + 1;     /* Don't forget the count-byte */
  73.     }
  74.     if (bumpmode == BUMP_CALC) {    /* Just calculating? */
  75.         return 1;                   /* Don't do the save */
  76.     }
  77.     if (bufcnt + tsize + 1 >= 4096 || tsize == 0) {
  78.         if (Write(SnapFile, buf, (LONG)bufcnt) == -1L) {
  79.             return 0;
  80.         }
  81.         bufcnt = 0;
  82.     }
  83.     buf[bufcnt++] = cnt;
  84.     CopyMem((char *)dataptr, (char *)&buf[bufcnt], tsize);
  85.     bufcnt += tsize;
  86.     return 1;
  87. }
  88.  
  89. ULONG WriteBody(BM)
  90. struct BitMap *BM;
  91. {
  92.     WORD scanline, plane;
  93.     REGISTER WORD bpr = BM->BytesPerRow;
  94.     REGISTER WORD i, j;
  95.     LONG offset = 0L;
  96.     REGISTER UBYTE data;
  97.     REGISTER UBYTE *bd;
  98.  
  99.     totalsize = 0L;
  100.  
  101.     if (!(buf = AllocMem(4096L, MEMF_PUBLIC))) {
  102.         return NULL;
  103.     }
  104.  
  105.     bufcnt = 0;
  106.     for (scanline = 0; scanline < BM->Rows; ++scanline) {
  107.         for (plane = 0; plane < BM->Depth; ++plane) {
  108.             bd = BM->Planes[plane]+offset;
  109.             i = 1;
  110.             j = bpr - 1;
  111.             data = bd[0];
  112.             while (j) {
  113.                 if (bd[i] == data) {        /* Equal bytes? */
  114.                     --i;                    /* First equal byte */
  115.                     if (i > 0) {            /* Old "random" data to save */
  116.                         if (!bump((WORD)(i - 1), bd, i)) {
  117.                             return NULL;
  118.                         }
  119.                     }
  120.                     bd = &bd[i];        /* Start of equal bytes */
  121.                     i = 2;              /* 0 & 1 is equal       */
  122.                     --j;
  123.                     while (i < 128 && j && bd[i] == data) {
  124.                         ++i;
  125.                         --j;
  126.                     }
  127.                     if (!bump((WORD)-(i - 1), &bd[i - 1], 1)) {
  128.                         return NULL;
  129.                     }
  130.                     goto new_block;
  131.                 } else {                    /* Not equal. Check block range */
  132.                     if (i == 128) {         /* Block limit                  */
  133.                         if (!bump((WORD)(i - 1), bd, i)) {
  134.                             return NULL;
  135.                         }
  136. new_block:
  137.                         bd = &bd[i];  /* Start new block              */
  138.                         i = 0;
  139.                         if (j == 0) {
  140.                             break;
  141.                         }
  142.                     }
  143.                 }
  144.                   /* Different byte or a new start */
  145.                 data = bd[i];               /* New possible equal       */
  146. next_byte:
  147.                 ++i;
  148.                 --j;
  149.             }
  150.             if (i != 0) {                   /* Data to save */
  151.                 if (!bump((WORD)(i - 1), bd, i)) {
  152.                     return NULL;
  153.                 }
  154.             }
  155.         }
  156.         offset += BM->BytesPerRow;
  157.     }
  158.     if (!bump(0, NULL, 0)) {   /* Flush any bytes left if the buffer */
  159.         return NULL;
  160.     }
  161.     FreeMem(buf, 4096L);
  162.     return totalsize;
  163. }
  164.  
  165. WORD SaveGS(GS)
  166. struct GfxSnap *GS;
  167. {
  168.     ULONG BODYPos;
  169.     UBYTE *oldtitle;
  170.  
  171.     oldtitle = GS->window->Title;
  172.     SetWindowTitles(GS->window, "Saving...", NULL);
  173.  
  174.     bumpmode = BUMP_SAVE;
  175.  
  176.     BMHdr.w = GS->BM.BytesPerRow * 8;
  177.     BMHdr.h = GS->height;
  178.     BMHdr.x = BMHdr.y = 0;
  179.     BMHdr.nPlanes = GS->depth;
  180.     BMHdr.masking = 0;
  181.     BMHdr.compression = 1;
  182.     BMHdr.transparentColor = dectoint(TranspBuf);
  183.     BMHdr.xAspect = BMHdr.xAspect = 1;
  184.     BMHdr.pageWidth = GS->pagew;
  185.     BMHdr.pageHeight = GS->pageh;
  186.     ViewMode = GS->viewmode;
  187.  
  188.     CMAP.ChunkSize = (LONG)3 * (GS->viewmode & HAM ? 16 : 1L << GS->depth);
  189.  
  190.     if (Write(SnapFile, (char *)&FORM,
  191.       (LONG)(sizeof(FORM) + sizeof(TYPE) +
  192.              sizeof(BMHD) + sizeof(BMHdr) +
  193.              sizeof(CAMG) + sizeof(ViewMode) +
  194.              sizeof(CMAP))) == -1L) {
  195.         return 0;
  196.     }
  197.     if (Write(SnapFile, (char *)&GS->rgb[0], CMAP.ChunkSize) == -1L) {
  198.         return 0;
  199.     }
  200.     BODYPos = Seek(SnapFile, 0L, OFFSET_CURRENT);
  201.     if (Write(SnapFile, (char *)&BODY, (LONG)sizeof(BODY)) == -1L) {
  202.         return 0;
  203.     }
  204.     if (!(BODY.ChunkSize = WriteBody(&GS->BM))) {
  205.         return 0;
  206.     }
  207.     FORM.ChunkSize = BODYPos - sizeof(FORM) + sizeof(BODY) + BODY.ChunkSize;
  208.     if (FORM.ChunkSize & 1) {                       /* Odd size */
  209.         if (Write(SnapFile, "X", 1L) == -1L) {
  210.             return 0;
  211.         }
  212.         ++FORM.ChunkSize;
  213.     }
  214.     Seek(SnapFile, 0L, OFFSET_BEGINNING);
  215.     Write(SnapFile, (char *)&FORM, (LONG)sizeof(FORM));
  216.     Seek(SnapFile, BODYPos, OFFSET_BEGINNING);
  217.     Write(SnapFile, (char *)&BODY, (LONG)sizeof(BODY));
  218.     SetWindowTitles(GS->window, oldtitle, NULL);
  219.     return 1;
  220. }
  221.